package com.cq.hd.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.constant.MsgConstant;
import com.cq.hd.common.constant.RedisKeyConstant;
import com.cq.hd.common.entity.BusinessInfo;
import com.cq.hd.common.entity.UserInfo;
import com.cq.hd.common.entity.mq.NotifyMsgSendDto;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.*;
import com.cq.hd.member.api.dto.*;
import com.cq.hd.member.api.vo.*;
import com.cq.hd.member.config.LockUtils;
import com.cq.hd.member.config.WxConfig;
import com.cq.hd.member.mapper.*;
import com.cq.hd.member.mq.provider.NotifyMsgProvider;
import com.cq.hd.member.po.*;
import com.cq.hd.member.service.TbAgentBindApplyService;
import com.cq.hd.member.service.TbAppUserService;
import com.cq.hd.member.service.TbBusinessService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.member.service.TbConfigSettingService;
import com.cq.hd.order.api.TbOrderApi;
import com.cq.hd.order.api.TbOrderSettleBillApi;
import com.cq.hd.order.api.dto.OrderDto;
import com.cq.hd.order.api.dto.OrderSettleBillDto;
import com.cq.hd.order.api.dto.OrderSettleBillUpdateStateDto;
import com.cq.hd.order.api.vo.OrderSettleBillVo;
import com.cq.hd.order.api.vo.OrderVo;
import com.cq.hd.product.api.TbActiveApi;
import com.cq.hd.product.api.dto.ActiveDto;
import com.cq.hd.product.api.vo.ActivePageVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 商家表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2023-11-21
 */
@Slf4j
@Service
public class TbBusinessServiceImpl extends ServiceImpl<TbBusinessMapper, TbBusinessPo> implements TbBusinessService {

    @Autowired
    private TbBusinessMerchantMapper businessMerchantMapper;

    @Autowired
    private TbBusinessSubscribeMapper businessSubscribeMapper;

    @Autowired
    private TbBusinessAgentMapper businessAgentMapper;

    @Autowired
    private TbMemberFeeBillMapper memberFeeBillMapper;

    @Autowired
    private TbMemberCardBillMapper memberCardBillMapper;

    @Autowired
    private TbActiveCountBillMapper activeCountBillMapper;

    @Autowired
    private TbBusinessEnterApplyMapper businessEnterApplyMapper;

    @Autowired
    private TbSubsidyAmtBillMapper subsidyAmtBillMapper;

    @Autowired
    private WxConfig wxConfig;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private TbActiveApi activeApi;

    @Autowired
    private TbOrderApi orderApi;

    @Autowired
    private TbOrderSettleBillApi orderSettleBillApi;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private NotifyMsgProvider notifyMsgProvider;

    @Autowired
    private TbSubsidyAmtBillMapper tbSubsidyAmtBillMapper;

    @Autowired
    private TbBusinessGroupMapper tbBusinessGroupMapper;

    @Autowired
    private TbBusinessPointsMallSettingsMapper tbBusinessPointsMallSettingsMapper;

    @Autowired
    private TbBusinessPointsMallProductMapper tbBusinessPointsMallCouponMapper;

    @Autowired
    private TbUserPointsAccountMapper tbUserPointsAccountMapper;

    @Autowired
    private TbBusinessPointsMallStatMapper mallStatMapper;

    @Autowired
    private TbConfigSettingService configSettingService;

    @Autowired
    private TbAppUserService appUserService;

    @Autowired
    private TbAgentBindApplyService agentBindApplyService;

    @Override
    public Page<BusinessPageVo> pageBusiness(BusinessPageDto businessPageDto) {
        String startTime = businessPageDto.getStartTime();
        String endTime = businessPageDto.getEndTime();
        if (!StringUtils.isBlank(startTime) && startTime.length() != 19) {
            Throw.isBusinessException("日期格式错误");
        }
        if (!StringUtils.isBlank(endTime) && endTime.length() != 19) {
            Throw.isBusinessException("日期格式错误");
        }

        PageHelper.startPage(businessPageDto.getPageNum(), businessPageDto.getPageSize());
        List<BusinessPageVo> businessPageVos = baseMapper.listBusinessByDto(businessPageDto);
        if (!CollectionUtils.isEmpty(businessPageVos)) {
            List<Long> businessIds = businessPageVos.stream().map(BusinessPageVo::getId).collect(Collectors.toList());

            // 根据商家id批量查询累计购卡和累计会员续费次数和金额
            Map<Long, List<TbMemberFeeBillPo>> memberFeeBillMap = new HashMap<>();
            List<TbMemberFeeBillPo> tbMemberFeeBillPos = memberFeeBillMapper.selectList(new QueryWrapper<TbMemberFeeBillPo>().eq("del_state", 0)
                    .eq("pay_state", PayStateEnum.SUCCESS.getValue())
                    .in("order_business_id", businessIds));
            if (!CollectionUtils.isEmpty(tbMemberFeeBillPos)) {
                memberFeeBillMap = tbMemberFeeBillPos.stream().collect(Collectors.groupingBy(TbMemberFeeBillPo::getOrderBusinessId));
            }

            Map<Long, List<TbMemberCardBillPo>> memberCardBillMap = new HashMap<>();
            List<TbMemberCardBillPo> tbMemberCardBillPos = memberCardBillMapper.selectList(new QueryWrapper<TbMemberCardBillPo>().eq("del_state", 0)
                    .eq("pay_state", PayStateEnum.SUCCESS.getValue())
                    .in("order_business_id", businessIds));
            if (!CollectionUtils.isEmpty(tbMemberCardBillPos)) {
                memberCardBillMap = tbMemberCardBillPos.stream().collect(Collectors.groupingBy(TbMemberCardBillPo::getOrderBusinessId));
            }

            LocalDateTime now = LocalDateTime.now();
            for (BusinessPageVo businessPageVo : businessPageVos) {
                // 累计购卡次数
                int buyCardCount = 0;
                // 累计购卡金额
                BigDecimal buyCardAmt = BigDecimal.ZERO;
                // 累计会员续费次数
                int memberFeeCount = 0;
                // 累计会员续费金额
                BigDecimal memberFeeAmt = BigDecimal.ZERO;

                // 会员状态：1-未开通，2-已开通，3-已过期
                Integer memberState = MemberStateEnum.NO.getValue();
                LocalDateTime memberExpireTime = businessPageVo.getMemberExpireTime();
                if (memberExpireTime != null) {
                    memberState = !now.isAfter(memberExpireTime) ? MemberStateEnum.YES.getValue() : MemberStateEnum.EXPIRE.getValue();
                }

                // 赠送的免费次数
                Integer activeCount = businessPageVo.getActiveCount();
                // 会员剩余次数
                int memberFeeActiveCount = 0;
                // 次卡剩余次数
                int memberCardActiveCount = 0;

                Long id = businessPageVo.getId();
                List<TbMemberFeeBillPo> tbMemberFeeBillPoList = memberFeeBillMap.get(id);
                if (!CollectionUtils.isEmpty(tbMemberFeeBillPoList)) {
                    memberFeeCount = tbMemberFeeBillPoList.size();
                    for (TbMemberFeeBillPo tbMemberFeeBillPo : tbMemberFeeBillPoList) {
                        BigDecimal memberFee = tbMemberFeeBillPo.getMemberFee();
                        memberFeeAmt = memberFeeAmt.add(memberFee);
                    }

                    // 会员未过期，累加未过期的剩余的会员发布次数
                    if (memberExpireTime != null && memberExpireTime.isAfter(now)) {
                        memberFeeActiveCount = tbMemberFeeBillPoList.stream()
                                .filter(billPo -> ExpireCancelStateEnum.NO_EXPIRE.getValue().equals(billPo.getExpireCancelState()))
                                .mapToInt(TbMemberFeeBillPo::getRemainActiveCount)
                                .sum();
                    }
                }

                List<TbMemberCardBillPo> tbMemberCardBillPoList = memberCardBillMap.get(id);
                if (!CollectionUtils.isEmpty(tbMemberCardBillPoList)) {
                    buyCardCount = tbMemberCardBillPoList.size();
                    for (TbMemberCardBillPo tbMemberCardBillPo : tbMemberCardBillPoList) {
                        BigDecimal cardCost = tbMemberCardBillPo.getCardCost();
                        buyCardAmt = buyCardAmt.add(cardCost);
                    }

                    // 会员未过期，累加剩余次卡次数
                    if (memberExpireTime != null && memberExpireTime.isAfter(now)) {
                        memberCardActiveCount = tbMemberCardBillPoList.stream().mapToInt(TbMemberCardBillPo::getRemainActiveCount).sum();
                    }
                }

                businessPageVo.setMemberState(memberState);
                businessPageVo.setBuyCardCount(buyCardCount);
                businessPageVo.setBuyCardAmt(buyCardAmt);
                businessPageVo.setMemberFeeCount(memberFeeCount);
                businessPageVo.setMemberFeeAmt(memberFeeAmt);
                businessPageVo.setRemainActiveCount(activeCount + memberFeeActiveCount + memberCardActiveCount);
            }
        }
        PageInfo<BusinessPageVo> pageInfo = new PageInfo<>(businessPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public Page<BusinessPointsMallPageVo> pagePointsMallBusiness(BusinessPointsMallPageDto businessPointsMallPageDto) {
        String startTime = businessPointsMallPageDto.getStartTime();
        String endTime = businessPointsMallPageDto.getEndTime();
        if (!StringUtils.isBlank(startTime) && startTime.length() != 19) {
            Throw.isBusinessException("开始日期格式错误");
        }
        if (!StringUtils.isBlank(endTime) && endTime.length() != 19) {
            Throw.isBusinessException("结束日期格式错误");
        }

        PageHelper.startPage(businessPointsMallPageDto.getPageNum(), businessPointsMallPageDto.getPageSize());
        List<BusinessPointsMallPageVo> businessPageVos = baseMapper.listPointsMallBusinessByDto(businessPointsMallPageDto);
        PageInfo<BusinessPointsMallPageVo> pageInfo = new PageInfo<>(businessPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public AdminBusinessPageVo details(Long id) {
        TbBusinessPo tbBusinessPo = baseMapper.selectById(id);
        if (tbBusinessPo != null) {
            AdminBusinessPageVo adminBusinessPageVo = new AdminBusinessPageVo();
            BeanUtils.copyProperties(tbBusinessPo, adminBusinessPageVo);

            // 查询商家入驻数据
            List<TbBusinessEnterApplyPo> businessEnterApplyPos = businessEnterApplyMapper.selectList(new QueryWrapper<TbBusinessEnterApplyPo>()
                    .eq("del_state", 0)
                    .eq("user_id", adminBusinessPageVo.getUserId())
                    .orderByDesc("create_time"));
            if (!CollectionUtils.isEmpty(businessEnterApplyPos)) {
                BusinessEnterApplyPageVo businessEnterApplyPageVo = new BusinessEnterApplyPageVo();
                BeanUtils.copyProperties(businessEnterApplyPos.get(0), businessEnterApplyPageVo);

                String bankCode = businessEnterApplyPageVo.getBankCode();
                if (!StringUtils.isBlank(bankCode)) {
                    HfBankIdEnum hfBankIdEnum = HfBankIdEnum.typeOfValue(bankCode);
                    if (hfBankIdEnum != null) {
                        businessEnterApplyPageVo.setBankName(hfBankIdEnum.getName());
                    }
                }

                // 法人证件类型
                String legalCertType = businessEnterApplyPageVo.getLegalCertType();
                if (!StringUtils.isBlank(legalCertType)) {
                    CertTypeEnum certTypeEnum = CertTypeEnum.typeOfValue(legalCertType);
                    if (certTypeEnum != null) {
                        businessEnterApplyPageVo.setLegalCertType(certTypeEnum.getName());
                    }
                }

                adminBusinessPageVo.setBusinessEnterApplyPageVo(businessEnterApplyPageVo);
            }

            BusinessVo businessVo = getActiveCount(tbBusinessPo.getUserId(), tbBusinessPo.getId());
            adminBusinessPageVo.setActiveCount(businessVo.getActiveCount());

            return adminBusinessPageVo;
        }
        return null;
    }

    /**
     * 邀请二级经纪人
     */
    private InviteMerchantVo inviteSubAgent(BusinessInviteDto businessInviteDto) {
        Long groupId = businessInviteDto.getGroupId();
        String inviteCode = businessInviteDto.getInviteCode();

        InviteMerchantVo inviteMerchantVo = new InviteMerchantVo();
        BeanUtils.copyProperties(businessInviteDto, inviteMerchantVo);

        if (groupId != null && groupId > 0) {
            TbBusinessGroupPo groupPo = tbBusinessGroupMapper.getGroupById(groupId);
            if (groupPo == null) {
                Throw.isBusinessException("分组ID有误");
            }
            inviteMerchantVo.setGroupName(groupPo.getGroupName());
        } else {
            groupId = 0L;
        }

        WxMiniCodeShareTypeEnum inviteBusinessEnum = WxMiniCodeShareTypeEnum.INVITE_AGENT;
        String param = inviteBusinessEnum.getName().replace("BUSINESS_CODE", inviteCode)
                .replace("GROUP_ID", String.valueOf(groupId));
        String miniImgUrl = wxConfig.getWxMiniCode(Constant.INVITE_AGENT_URL_PAGE, param, inviteBusinessEnum.getValue(), inviteCode + "-" + groupId);
        if (StringUtils.isBlank(miniImgUrl)) {
            log.error("一级经纪人邀请二级经纪人邀请码生成失败,inviteCode:{}", inviteCode);
            Throw.isBusinessException("邀请失败");
        }
        inviteMerchantVo.setMiniImgUrl(miniImgUrl);

        return inviteMerchantVo;
    }

    public void checkBusinessMaxInviteAgentCount(Long businessId) {
        TbBusinessPo businessPo = baseMapper.selectById(businessId);
        if (businessPo == null || businessPo.getDelState() != 0) {
            Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
        }

        Integer maxCount = businessPo.getMaxInviteAgentCount();
        // 不限
        if (maxCount == null) {
            return;
        }

        // 商家当前经纪人数量
        Integer count = businessAgentMapper.selectCount(new QueryWrapper<TbBusinessAgentPo>()
                .eq("del_state", 0)
                .eq("business_id", businessId));
        if (count != null && count >= maxCount) {
            Throw.isBusinessException("您的经纪人数量已达上限");
        }
    }

    @Override
    public InviteMerchantVo invite(BusinessInviteDto businessInviteDto) {
        InviteMerchantVo inviteMerchantVo = new InviteMerchantVo();

        Integer type = businessInviteDto.getType();
        // 邀请二级经纪人
        if (Objects.equals(type, InviteTypeEnum.INVITE_SUB_AGENT.getValue())) {
            return inviteSubAgent(businessInviteDto);
        }

        // 后面还是走奥特曼的代码
        String inviteCode = businessInviteDto.getInviteCode();
        String businessName = businessInviteDto.getBusinessName();
        String businessShortName = businessInviteDto.getBusinessShortName();
        String logo = businessInviteDto.getLogo();
        Long businessId = businessInviteDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            Long userId = businessInviteDto.getUserId();
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);
            businessId = tbBusinessPo.getId();
            businessName = tbBusinessPo.getBusinessName();
            businessShortName = tbBusinessPo.getBusinessShortName();
            logo = tbBusinessPo.getLogo();
            inviteCode = tbBusinessPo.getInviteCode();
        }

        // 判断商家是否到了可邀请经纪人数量的限制
        checkBusinessMaxInviteAgentCount(businessId);

        Long businessGroupId = businessInviteDto.getGroupId();

        // 根据邀请码生成小程序码
        String miniImgUrl = "";
        if (InviteTypeEnum.INVITE_MERCHANT.getValue().equals(type)) {
            WxMiniCodeShareTypeEnum inviteBusinessEnum = WxMiniCodeShareTypeEnum.INVITE_MERCHANT;
            String param = inviteBusinessEnum.getName().replace("BUSINESS_CODE", inviteCode);
            miniImgUrl = wxConfig.getWxMiniCode(Constant.INVITE_MERCHANT_URL_PAGE, param, inviteBusinessEnum.getValue(), inviteCode);
        } else if (InviteTypeEnum.INVITE_AGENT.getValue().equals(type)) {
            // 商家邀请经纪人，增加分组id字段处理
            if (businessGroupId != null && businessGroupId > 0) {
                TbBusinessGroupPo businessGroupPo = tbBusinessGroupMapper.getGroupById(businessGroupId);
                if (businessGroupPo == null) {
                    Throw.isBusinessException("商家分组ID有误");
                }
                inviteMerchantVo.setGroupName(businessGroupPo.getGroupName());
            } else {
                businessGroupId = 0L;
            }

            WxMiniCodeShareTypeEnum inviteBusinessEnum = WxMiniCodeShareTypeEnum.INVITE_AGENT;
            String param = inviteBusinessEnum.getName().replace("BUSINESS_CODE", inviteCode)
                    .replace("GROUP_ID", String.valueOf(businessGroupId));
            miniImgUrl = wxConfig.getWxMiniCode(Constant.INVITE_AGENT_URL_PAGE, param, inviteBusinessEnum.getValue(), inviteCode + "-" + businessGroupId);
        }

        if (StringUtils.isBlank(miniImgUrl)) {
            log.error("生成邀请商户/经纪人小程序码失败,inviteCode:{}", inviteCode);
            Throw.isBusinessException("邀请失败");
        }

        inviteMerchantVo.setBusinessName(businessName);
        inviteMerchantVo.setBusinessShortName(businessShortName);
        inviteMerchantVo.setInviteCode(businessInviteDto.getInviteCode());
        inviteMerchantVo.setLogo(logo);
        inviteMerchantVo.setMiniImgUrl(miniImgUrl);

        return inviteMerchantVo;
    }

    @Override
    public Boolean unBindMerchant(BusinessMerchantUnBindDto businessMerchantUnBindDto) {
        Long id = businessMerchantUnBindDto.getId();
        if (id == null || id <= 0) {
            Throw.isBusinessException("请选择解除的商户");
        }

        String businessShortName = businessMerchantUnBindDto.getBusinessShortName();
        Long userId = businessMerchantUnBindDto.getUserId();
        Long businessId = businessMerchantUnBindDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);

            businessShortName = tbBusinessPo.getBusinessShortName();
            businessId = tbBusinessPo.getId();
            businessMerchantUnBindDto.setBusinessId(businessId);
        }

        List<TbBusinessMerchantPo> tbBusinessMerchantPos = businessMerchantMapper.selectList(new QueryWrapper<TbBusinessMerchantPo>().eq("del_state", 0)
                .eq("business_id", businessId)
                .eq("merchant_id", id));
        if (CollectionUtils.isEmpty(tbBusinessMerchantPos)) {
            Throw.isBusinessException("未找到商户绑定数据");
        }

        TbBusinessMerchantPo tbBusinessMerchantPo = tbBusinessMerchantPos.get(0);
        LocalDateTime now = LocalDateTime.now();

        // 判断是否存在与该商户的商品的发布的活动，是否已过期
        ActiveDto activeDto = new ActiveDto();
        activeDto.setMerchantIdStr(id + ",");
        activeDto.setBusinessId(businessId);
        activeDto.setActiveStates(Arrays.asList(ActiveStateEnum.NO_START.getValue(), ActiveStateEnum.IN_PROGRESS.getValue(), ActiveStateEnum.ENDED.getValue()));
        activeDto.setDelState(0);
        List<ActivePageVo> activePageVos = activeApi.listByDto(activeDto).unpack();
        if (!CollectionUtils.isEmpty(activePageVos)) {
            // 判断是否存在进行中的活动，活动有效期是否已过期
            for (ActivePageVo activePageVo : activePageVos) {
                LocalDateTime startTime = activePageVo.getStartTime();
                LocalDateTime endTime = activePageVo.getEndTime();
                LocalDateTime validStartTime = activePageVo.getValidStartTime();
                LocalDateTime validEndTime = activePageVo.getValidEndTime();

                if (startTime.compareTo(now) > 0) {
                    // 存在已发布未开始的活动
                    Throw.isBusinessException("该商户关联了进行中的活动，无法解除");
                } else if (endTime.compareTo(now) <= 0) {
                    // 存在已结束的活动，需要判断活动有效期是否过期

                    if (validStartTime.compareTo(now) > 0) {
                        // 存在未开始的有效活动
                        Throw.isBusinessException("该商户关联的活动未过有效期，无法解除");
                    }

                    if (validStartTime.compareTo(now) <= 0 && validEndTime.compareTo(now) > 0) {
                        // 存在进行中的有效活动
                        Throw.isBusinessException("该商户关联的活动未过有效期，无法解除");
                    }
                } else if (startTime.compareTo(now) <= 0 && endTime.compareTo(now) > 0) {
                    // 存在进行中的活动
                    Throw.isBusinessException("该商户关联了进行中的活动，无法解除");
                }
            }
        }

        // 如果是自有商户，不能被删除
        Integer ownState = tbBusinessMerchantPo.getOwnState();
        if (OwnStateEnum.YES.getValue().equals(ownState)) {
            Throw.isBusinessException("不能解绑自有商户");
        }

        tbBusinessMerchantPo.setDelState(1);
        tbBusinessMerchantPo.setUpdateTime(now);
        int update = businessMerchantMapper.updateById(tbBusinessMerchantPo);
        if (update == 0) {
            Throw.isBusinessException("解绑失败");
        }

        // 发送策划人解绑通知系统通知
        NotifyMsgSendDto notifyMsgSendDto = new NotifyMsgSendDto();
        notifyMsgSendDto.setUserId(tbBusinessMerchantPo.getMerchantId());
        notifyMsgSendDto.setRoleType(RoleTypeEnum.MERCHANT.getValue());
        notifyMsgSendDto.setMsgType(NotifyMsgTypeEnum.MERCHANT_UNBIND_BUSINESS.getValue());
        notifyMsgSendDto.setContent(String.format(MsgConstant.MERCHANT_UNBIND_BUSINESS, businessShortName));
        notifyMsgSendDto.setMsgState(NotifyMsgStateEnum.NO_READ.getValue());
        notifyMsgProvider.sendMsg(notifyMsgSendDto);

        return true;
    }

    @Override
    public Page<RelationMerchantPageVo> pageRelationMerchant(RelationMerchantPageDto relationMerchantPageDto) {
        Long userId = relationMerchantPageDto.getUserId();
        Long id = relationMerchantPageDto.getId();
        if (id == null || id <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            relationMerchantPageDto.setId(tbBusinessPos.get(0).getId());
        }

        PageHelper.startPage(relationMerchantPageDto.getPageNum(), relationMerchantPageDto.getPageSize());
        List<RelationMerchantPageVo> businessMerchantVos = businessMerchantMapper.lisRelationMerchantByDto(relationMerchantPageDto);
        PageInfo<RelationMerchantPageVo> pageInfo = new PageInfo<>(businessMerchantVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public List<Long> listRelationMerchantId(Long userId, Long businessId) {
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            businessId = tbBusinessPos.get(0).getId();
        }

        return businessMerchantMapper.listRelationMerchantId(businessId);
    }

    @Override
    public BusinessPageVo getByUserId(Long userId) {
        List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("state", 1)
                .eq("user_id", userId));
        if (!CollectionUtils.isEmpty(tbBusinessPos)) {
            TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);
            BusinessPageVo businessPageVo = new BusinessPageVo();
            BeanUtils.copyProperties(tbBusinessPo, businessPageVo);
            return businessPageVo;
        }
        return null;
    }

    @Override
    public BusinessHomePageVo getHomePage(Long id, Long userId) {
        TbBusinessPo tbBusinessPo;
        if (id == null || id == 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("state", 1).eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            tbBusinessPo = tbBusinessPos.get(0);
            id = tbBusinessPo.getId();
        } else {
            tbBusinessPo = baseMapper.selectById(id);
        }

        if (tbBusinessPo == null) {
            return null;
        }

        BusinessHomePageVo businessHomePageVo = new BusinessHomePageVo();
        BeanUtils.copyProperties(tbBusinessPo, businessHomePageVo);
        businessHomePageVo.setMobile(PrivacyUtil.encryptMobile(businessHomePageVo.getMobile()));

        List<Long> subscribeUserIds = new ArrayList<>();
        // 查询商家订阅列表
        List<BusinessSubscribeVo> businessSubscribeVos = businessSubscribeMapper.listByBusinessIds(Collections.singletonList(id));
        if (!CollectionUtils.isEmpty(businessSubscribeVos)) {
            subscribeUserIds = businessSubscribeVos.stream().map(BusinessSubscribeVo::getUserId).collect(Collectors.toList());
            // 订阅个数
            businessHomePageVo.setSubscribeCount(businessSubscribeVos.size());
        }

        if (userId != null && userId > 0) {
            // 用户是否订阅
            if (subscribeUserIds.contains(userId)) {
                // 订阅状态：1-未订阅，2-已订阅
                businessHomePageVo.setSubscribeState(2);
            }

            // 判断当前登录用户是否是该商家的经纪人
            Integer count = businessAgentMapper.selectCount(new QueryWrapper<TbBusinessAgentPo>().eq("del_state", 0)
                    .eq("user_id", userId).eq("business_id", id));
            if (count != null && count > 0) {
                // 是否是该商家的经纪人：1-不是，2-是
                businessHomePageVo.setAgentState(2);
            }
        }

        // 如果有开启积分商城，需要查询当前账号可用积分
        if (businessHomePageVo.getPointsMallState().equals(BusinessPointsMallStateEnum.OPEN.getValue())) {
            TbUserPointsAccountPo accountPo = tbUserPointsAccountMapper.getAccount(id, userId);
            if (accountPo != null) {
                businessHomePageVo.setMyRemainPoint(accountPo.getRemainPoint());
            }
        }

        // 分销申请开关是否展示
        setAgentApplyEnable(businessHomePageVo, tbBusinessPo.getUserId(), userId);

        return businessHomePageVo;
    }

    private void setAgentApplyEnable(BusinessHomePageVo businessHomePageVo, Long businessUserId, Long userId) {
        String agentApplyEnable = configSettingService.getUserConfigValueOfDefault(
                businessUserId, ConfigSettingKeyEnum.BUSINESS_AGENT_APPLY_ENABLE.name());
        // 没有开启申请入口
        if (agentApplyEnable == null || "false".equals(agentApplyEnable)) {
            businessHomePageVo.setAgentApplyState(BusinessPageAgentApplyStateEnum.NONE.getValue());
            return;
        }

        // 判断是否已经是商家经纪人
        if (businessHomePageVo.getAgentState() == 2) {
            businessHomePageVo.setAgentApplyState(BusinessPageAgentApplyStateEnum.AGENT.getValue());
            return;
        }

        AppUserVo loginUserInfo = appUserService.getAppUserById(userId);
        // 二级经纪人不展示申请入口
        if (loginUserInfo == null || loginUserInfo.getAgentLevel() == 2) {
            businessHomePageVo.setAgentApplyState(BusinessPageAgentApplyStateEnum.NONE.getValue());
            return;
        }

        // 判断是否在申请中
        TbAgentBindApplyPo latestBusinessAgentApply = agentBindApplyService.getLatestBusinessAgentApply(businessHomePageVo.getId(), userId);
        if (latestBusinessAgentApply != null && AgentBindApplyAuditStateEnum.AUDIT_PENDING.getValue().equals(latestBusinessAgentApply.getAuditState())) {
            businessHomePageVo.setAgentApplyState(BusinessPageAgentApplyStateEnum.APPLYING.getValue());
            return;
        }

        businessHomePageVo.setAgentApplyState(BusinessPageAgentApplyStateEnum.CAN_APPLY.getValue());
    }

    @Override
    public Boolean updateHomePage(UpdateHomePageDto updateHomePageDto) {
        Long userId = updateHomePageDto.getUserId();
        Long id = updateHomePageDto.getId();
        String provinceName = updateHomePageDto.getProvinceName();
        String cityName = updateHomePageDto.getCityName();

        if (StringUtils.isBlank(provinceName) || StringUtils.isBlank(cityName)) {
            Throw.isBusinessException("请定位位置信息");
        }


        if (id == null || id <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            id = tbBusinessPos.get(0).getId();
        }

        TbBusinessPo tbBusinessPo = baseMapper.selectById(id);
        if (tbBusinessPo == null || tbBusinessPo.getDelState() != 0) {
            Throw.isBusinessException("未找到商家数据");
        }

        tbBusinessPo.setBusinessShortName(updateHomePageDto.getBusinessName());
        tbBusinessPo.setLogo(updateHomePageDto.getLogo());
        if (!CollectionUtils.isEmpty(updateHomePageDto.getBusinessIntroductions())) {
            tbBusinessPo.setIntroduction(JSON.toJSONString(updateHomePageDto.getBusinessIntroductions()));
        }
        tbBusinessPo.setIntroductionImg(updateHomePageDto.getIntroductionImg());
        tbBusinessPo.setProvinceName(updateHomePageDto.getProvinceName());
        tbBusinessPo.setCityName(updateHomePageDto.getCityName());
        tbBusinessPo.setPosition(updateHomePageDto.getPosition());
        tbBusinessPo.setHomeBackgroundImage(updateHomePageDto.getHomeBackgroundImage());
        tbBusinessPo.setUpdateTime(LocalDateTime.now());
        int update = baseMapper.updateById(tbBusinessPo);
        if (update <= 0) {
            Throw.isBusinessException("更新失败");
        }

        // 将最新的用户数据缓存Redis
        String userInfoRedis = redisUtil.get(String.format(RedisKeyConstant.USER_INFO_KEY, tbBusinessPo.getUserId()));
        if (!StringUtils.isNullOrEmpty(userInfoRedis)) {
            UserInfo userInfo = JSON.parseObject(userInfoRedis, UserInfo.class);
            BusinessInfo businessInfo = new BusinessInfo();
            BeanUtils.copyProperties(tbBusinessPo, businessInfo);
            userInfo.setBusinessInfo(businessInfo);

            redisUtil.set(String.format(RedisKeyConstant.USER_INFO_KEY, tbBusinessPo.getUserId()), JSON.toJSONString(userInfo), Constant.USER_LOGIN_TIMEOUT, TimeUnit.SECONDS);
        }

        return true;
    }

    @Override
    public BusinessShareVo shareHomePage(BusinessShareDto businessShareDto) {
        Long id = businessShareDto.getId();
        TbBusinessPo tbBusinessPo = baseMapper.selectById(id);
        if (tbBusinessPo == null || tbBusinessPo.getDelState() != 0) {
            Throw.isBusinessException("未找到商家数据");
        }

        WxMiniCodeShareTypeEnum wxMiniCodeShareTypeEnum = WxMiniCodeShareTypeEnum.BUSINESS_SHARE;
        String param = wxMiniCodeShareTypeEnum.getName().replace("BUSINESS_ID", String.valueOf(id));
        String miniImgUrl = wxConfig.getWxMiniCode(Constant.BUSINESS_SHARE_URL_PAGE, param, wxMiniCodeShareTypeEnum.getValue(), String.valueOf(id));
        if (StringUtils.isBlank(miniImgUrl)) {
            log.error("生成分享商家主页小程序码失败,businessId:{}", id);
            Throw.isBusinessException("分享失败");
        }

        BusinessShareVo businessShareVo = new BusinessShareVo();
        businessShareVo.setBusinessName(tbBusinessPo.getBusinessName());
        businessShareVo.setBusinessShortName(tbBusinessPo.getBusinessShortName());
        businessShareVo.setLogo(tbBusinessPo.getLogo());
        businessShareVo.setIntroduction(tbBusinessPo.getIntroduction());

        Integer businessSubscribeCount = businessSubscribeMapper.selectCount(new QueryWrapper<TbBusinessSubscribePo>().eq("del_state", 0)
                .eq("business_id", id));
        // 订阅个数
        businessShareVo.setSubscribeCount(businessSubscribeCount == null ? 0 : businessSubscribeCount);
        // 活动个数
        Integer activeCount = activeApi.countByBusinessId(id).unpack();
        businessShareVo.setActiveCount(activeCount == null ? 0 : activeCount);
        // 购买用户数
        int buyNum = 0;
        OrderDto orderDto = new OrderDto();
        orderDto.setBusinessId(id);
        orderDto.setOrderStates(Arrays.asList(OrderStateEnum.WAIT_VERIFY.getValue(),
                OrderStateEnum.VERIFYING.getValue(),
                OrderStateEnum.FINISH.getValue(),
                OrderStateEnum.VERIFIED.getValue()));
        List<OrderVo> orderVos = orderApi.listByDto(orderDto).unpack();
        if (!CollectionUtils.isEmpty(orderVos)) {
            buyNum = orderVos.stream().map(OrderVo::getUserId).collect(Collectors.toSet()).size();
        }
        businessShareVo.setBuyCount(buyNum);
        businessShareVo.setMiniImgUrl(miniImgUrl);

        return businessShareVo;
    }

    @Override
    public BusinessPageVo getByMobile(String mobile) {
        List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("mobile", mobile));
        if (!CollectionUtils.isEmpty(tbBusinessPos)) {
            TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);
            BusinessPageVo businessPageVo = new BusinessPageVo();
            BeanUtils.copyProperties(tbBusinessPo, businessPageVo);
            return businessPageVo;
        }
        return null;
    }

    @Override
    public BusinessPageVo getByInviteCode(String inviteCode) {
        List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("invite_code", inviteCode));
        if (!CollectionUtils.isEmpty(tbBusinessPos)) {
            TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);
            BusinessPageVo businessPageVo = new BusinessPageVo();
            BeanUtils.copyProperties(tbBusinessPo, businessPageVo);
            return businessPageVo;
        }
        return null;
    }

    @Override
    public BusinessPageVo getBusinessById(Long businessId) {
        TbBusinessPo businessPo = baseMapper.selectById(businessId);
        if (businessPo != null && businessPo.getDelState() == 0) {
            BusinessPageVo businessPageVo = new BusinessPageVo();
            BeanUtils.copyProperties(businessPo, businessPageVo);
            return businessPageVo;
        }
        return null;
    }

    @Override
    public List<BusinessVo> listBusinessByIds(List<Long> ids) {
        return baseMapper.listBusinessByIds(ids);
    }

    @Override
    public Page<BusinessVo> searchByBusinessName(Integer pageNum, Integer pageSize, String keyword) {
        PageHelper.startPage(pageNum, pageSize);
        List<BusinessVo> businessVos = baseMapper.listByBusinessName(keyword);
        PageInfo<BusinessVo> pageInfo = new PageInfo<>(businessVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public BusinessVo getActiveCount(Long userId, Long businessId) {
        TbBusinessPo tbBusinessPo;
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                // 如果不是商家，则返回空
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            tbBusinessPo = tbBusinessPos.get(0);
            businessId = tbBusinessPo.getId();
        } else {
            tbBusinessPo = baseMapper.selectById(businessId);
            if (tbBusinessPo == null || tbBusinessPo.getDelState() != 0) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }
        }

        // 赠送免费次数
        Integer activeCount = tbBusinessPo.getActiveCount();
        int memberFeeActiveCount = 0;
        int memberCardActiveCount = 0;
        LocalDateTime now = LocalDateTime.now();

        // 判断是否是会员，会员是否到期
        LocalDateTime memberExpireTime = tbBusinessPo.getMemberExpireTime();
        if (memberExpireTime != null) {
            if (memberExpireTime.isAfter(now)) {
                // 会员没过期，查询会员开通续费的流水，累加未到期作废的次数，查询开通次卡的流水，累加剩余次数
                List<TbMemberFeeBillPo> tbMemberFeeBillPos = memberFeeBillMapper.selectList(new QueryWrapper<TbMemberFeeBillPo>().eq("del_state", 0)
                        .eq("order_business_id", businessId)
                        .eq("pay_state", PayStateEnum.SUCCESS.getValue())
                        .eq("expire_cancel_state", ExpireCancelStateEnum.NO_EXPIRE.getValue()));
                if (!CollectionUtils.isEmpty(tbMemberFeeBillPos)) {
                    memberFeeActiveCount = tbMemberFeeBillPos.stream().mapToInt(TbMemberFeeBillPo::getRemainActiveCount).sum();
                }

                List<TbMemberCardBillPo> tbMemberCardBillPos = memberCardBillMapper.selectList(new QueryWrapper<TbMemberCardBillPo>().eq("del_state", 0)
                        .eq("order_business_id", businessId)
                        .eq("pay_state", PayStateEnum.SUCCESS.getValue()));
                if (!CollectionUtils.isEmpty(tbMemberCardBillPos)) {
                    memberCardActiveCount = tbMemberCardBillPos.stream().mapToInt(TbMemberCardBillPo::getRemainActiveCount).sum();
                }
            }
        }

        BusinessVo businessVo = new BusinessVo();
        BeanUtils.copyProperties(tbBusinessPo, businessVo);
        businessVo.setActiveCount(activeCount + memberFeeActiveCount + memberCardActiveCount);

        return businessVo;
    }

    @Override
    public Boolean subActiveCount(UpdateActiveCountDto updateActiveCountDto) {
        Integer tradeActiveCount = updateActiveCountDto.getTradeActiveCount();
        Long businessId = updateActiveCountDto.getBusinessId();
        TbBusinessPo tbBusinessPo = baseMapper.selectById(businessId);
        if (tbBusinessPo == null) {
            Throw.isBusinessException("未找到商家数据");
        }

        LocalDateTime now = LocalDateTime.now();

        // 扣除免费次数个数
        int subActiveCount = 0;
        // 扣除会费次数
        List<TbMemberFeeBillPo> memberFeeBillPos = new ArrayList<>();
        // 扣除购买次卡次数
        List<TbMemberCardBillPo> memberCardBillPos = new ArrayList<>();
        String remark = "";

        // 扣减活动次数顺序：免费次数>会费次数>购买次数
        Integer activeCount = tbBusinessPo.getActiveCount();
        if (activeCount >= tradeActiveCount) {
            subActiveCount = tradeActiveCount;
            remark += "扣减免费次数=" + tradeActiveCount;
        } else {
            if (activeCount > 0) {
                subActiveCount = activeCount;
                remark += "扣减免费次数=" + activeCount;
            }

            LocalDateTime memberExpireTime = tbBusinessPo.getMemberExpireTime();
            if (memberExpireTime == null) {
                // 未开通会员
                Throw.isBusinessException("赠送次数已用完，请开通会员");
            }

            if (!now.isBefore(memberExpireTime)) {
                // 会员已过期
                Throw.isBusinessException("会员已过期，发布活动次数不足");
            }

            // 会员没过期，查询会员开通续费的流水，累加未到期作废的次数，查询开通次卡的流水，累加剩余次数
            List<TbMemberFeeBillPo> tbMemberFeeBillPos = memberFeeBillMapper.selectList(new QueryWrapper<TbMemberFeeBillPo>().eq("del_state", 0)
                    .eq("order_business_id", businessId)
                    .eq("pay_state", PayStateEnum.SUCCESS.getValue())
                    .eq("expire_cancel_state", ExpireCancelStateEnum.NO_EXPIRE.getValue()));
            if (CollectionUtils.isEmpty(tbMemberFeeBillPos)) {
                Throw.isBusinessException("发布活动次数不足");
            }

            int memberFeeActiveCount = tbMemberFeeBillPos.stream().mapToInt(TbMemberFeeBillPo::getRemainActiveCount).sum();
            if (activeCount + memberFeeActiveCount < tradeActiveCount) {
                if (memberFeeActiveCount > 0) {
                    // 根据支付时间倒序扣除
                    tbMemberFeeBillPos = tbMemberFeeBillPos.stream()
                            .sorted(Comparator.comparing(TbMemberFeeBillPo::getPayTime).reversed())
                            .collect(Collectors.toList());

                    // 更新会员剩余活动次数
                    int subMemberFeeActiveCount = memberFeeActiveCount;
                    if (StringUtils.isBlank(remark)) {
                        remark += "扣减会员发布次数=" + subMemberFeeActiveCount;
                    } else {
                        remark += ",扣减会员发布次数=" + subMemberFeeActiveCount;
                    }


                    for (TbMemberFeeBillPo tbMemberFeeBillPo : tbMemberFeeBillPos) {
                        Integer remainActiveCount = tbMemberFeeBillPo.getRemainActiveCount();
                        if (remainActiveCount <= 0) {
                            continue;
                        }

                        if (subMemberFeeActiveCount - remainActiveCount == 0) {
                            tbMemberFeeBillPo.setRemainActiveCount(remainActiveCount);
                            memberFeeBillPos.add(tbMemberFeeBillPo);
                            break;
                        }

                        if (subMemberFeeActiveCount - remainActiveCount < 0) {
                            tbMemberFeeBillPo.setRemainActiveCount(subMemberFeeActiveCount);
                            memberFeeBillPos.add(tbMemberFeeBillPo);
                            break;
                        }
                        memberFeeBillPos.add(tbMemberFeeBillPo);

                        subMemberFeeActiveCount = subMemberFeeActiveCount - remainActiveCount;
                    }
                }

                // 查询次卡
                List<TbMemberCardBillPo> tbMemberCardBillPos = memberCardBillMapper.selectList(new QueryWrapper<TbMemberCardBillPo>().eq("del_state", 0)
                        .eq("order_business_id", businessId)
                        .eq("pay_state", PayStateEnum.SUCCESS.getValue()));
                if (CollectionUtils.isEmpty(tbMemberCardBillPos)) {
                    Throw.isBusinessException("发布活动次数不足");
                }

                int memberCardActiveCount = tbMemberCardBillPos.stream().mapToInt(TbMemberCardBillPo::getRemainActiveCount).sum();
                if (activeCount + memberFeeActiveCount + memberCardActiveCount < tradeActiveCount) {
                    Throw.isBusinessException("发布活动次数不足");
                } else {
                    // 根据支付时间倒序扣除
                    tbMemberCardBillPos = tbMemberCardBillPos.stream()
                            .sorted(Comparator.comparing(TbMemberCardBillPo::getPayTime).reversed())
                            .collect(Collectors.toList());

                    // 更新次卡剩余活动次数
                    int subMemberCardActiveCount = tradeActiveCount - activeCount - memberFeeActiveCount;
                    if (StringUtils.isBlank(remark)) {
                        remark += "扣减次卡次数=" + subMemberCardActiveCount;
                    } else {
                        remark += ",扣减次卡次数=" + subMemberCardActiveCount;
                    }

                    for (TbMemberCardBillPo tbMemberCardBillPo : tbMemberCardBillPos) {
                        Integer remainActiveCount = tbMemberCardBillPo.getRemainActiveCount();
                        if (remainActiveCount <= 0) {
                            continue;
                        }

                        if (subMemberCardActiveCount - remainActiveCount == 0) {
                            tbMemberCardBillPo.setRemainActiveCount(remainActiveCount);
                            memberCardBillPos.add(tbMemberCardBillPo);
                            break;
                        }

                        if (subMemberCardActiveCount - remainActiveCount < 0) {
                            tbMemberCardBillPo.setRemainActiveCount(subMemberCardActiveCount);
                            memberCardBillPos.add(tbMemberCardBillPo);
                            break;
                        }
                        memberCardBillPos.add(tbMemberCardBillPo);

                        subMemberCardActiveCount = subMemberCardActiveCount - remainActiveCount;
                    }
                }
            } else {
                // 根据支付时间倒序扣除
                tbMemberFeeBillPos = tbMemberFeeBillPos.stream()
                        .sorted(Comparator.comparing(TbMemberFeeBillPo::getPayTime).reversed())
                        .collect(Collectors.toList());

                // 更新会员剩余活动次数
                int subMemberFeeActiveCount = tradeActiveCount - activeCount;
                if (StringUtils.isBlank(remark)) {
                    remark += "扣减会员发布次数=" + subMemberFeeActiveCount;
                } else {
                    remark += ",扣减会员发布次数=" + subMemberFeeActiveCount;
                }

                for (TbMemberFeeBillPo tbMemberFeeBillPo : tbMemberFeeBillPos) {
                    Integer remainActiveCount = tbMemberFeeBillPo.getRemainActiveCount();
                    if (remainActiveCount <= 0) {
                        continue;
                    }

                    if (subMemberFeeActiveCount - remainActiveCount == 0) {
                        tbMemberFeeBillPo.setRemainActiveCount(remainActiveCount);
                        memberFeeBillPos.add(tbMemberFeeBillPo);
                        break;
                    }

                    if (subMemberFeeActiveCount - remainActiveCount < 0) {
                        tbMemberFeeBillPo.setRemainActiveCount(subMemberFeeActiveCount);
                        memberFeeBillPos.add(tbMemberFeeBillPo);
                        break;
                    }
                    memberFeeBillPos.add(tbMemberFeeBillPo);

                    subMemberFeeActiveCount = subMemberFeeActiveCount - remainActiveCount;
                }
            }
        }

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 扣减商家相关活动次数
            if (subActiveCount > 0) {
                // 扣除免费次数
                int count = baseMapper.subActiveCount(businessId, subActiveCount, now);
                if (count == 0) {
                    log.error("扣除商家免费次数失败");
                    Throw.isBusinessException("发布活动次数不足");
                }
            }

            if (!CollectionUtils.isEmpty(memberFeeBillPos)) {
                // 扣除会费次数
                for (TbMemberFeeBillPo memberFeeBillPo : memberFeeBillPos) {
                    Long id = memberFeeBillPo.getId();
                    Integer remainActiveCount = memberFeeBillPo.getRemainActiveCount();
                    int count = memberFeeBillMapper.subRemainActiveCount(id, remainActiveCount, now);
                    if (count == 0) {
                        log.error("扣除商家会员次数失败");
                        Throw.isBusinessException("发布活动次数不足");
                    }
                }
            }

            if (!CollectionUtils.isEmpty(memberCardBillPos)) {
                // 扣除购买次卡次数
                for (TbMemberCardBillPo memberCardBillPo : memberCardBillPos) {
                    Long id = memberCardBillPo.getId();
                    Integer remainActiveCount = memberCardBillPo.getRemainActiveCount();
                    int count = memberCardBillMapper.subRemainActiveCount(id, remainActiveCount, now);
                    if (count == 0) {
                        log.error("扣除商家次卡次数失败");
                        Throw.isBusinessException("发布活动次数不足");
                    }
                }
            }

            // 增加流水
            TbActiveCountBillPo tbActiveCountBillPo = new TbActiveCountBillPo();
            tbActiveCountBillPo.setBusinessId(businessId);
            tbActiveCountBillPo.setUserId(tbBusinessPo.getUserId());
            tbActiveCountBillPo.setBillType(BillTypeEnum.EXPEND.getValue());
            tbActiveCountBillPo.setTradeType(updateActiveCountDto.getTradeType());
            tbActiveCountBillPo.setTradeCount(tradeActiveCount);
            tbActiveCountBillPo.setRelationId(updateActiveCountDto.getRelationId());
            tbActiveCountBillPo.setTradeTime(updateActiveCountDto.getTradeTime());
            tbActiveCountBillPo.setRemark(remark);
            tbActiveCountBillPo.setCreateTime(now);
            tbActiveCountBillPo.setUpdateTime(now);
            int count = activeCountBillMapper.insert(tbActiveCountBillPo);
            if (count == 0) {
                log.error("新增活动次数流水失败");
                Throw.isBusinessException("扣减活动次数异常");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<扣减商家发布活动次数>事务异常回滚", e);
//            Throw.isBusinessException("扣减活动次数异常");
            return false;
        }

        return true;
    }

    @Override
    public Boolean scanBusinessMemberExpireJob() {
        List<TbBusinessPo> businessPos = baseMapper.selectList(new QueryWrapper<TbBusinessPo>().le("member_expire_time", LocalDateTime.now()));
        if (CollectionUtils.isEmpty(businessPos)) {
            return true;
        }

        for (TbBusinessPo businessPo : businessPos) {
            memberFeeBillMapper.updateExpireCancelState(ExpireCancelStateEnum.EXPIRE.getValue(),
                    PayStateEnum.SUCCESS.getValue(), businessPo.getId());
        }

        return true;
    }

    @Override
    public Integer getNewCountByDate(String startTime, String endTime) {
        return baseMapper.selectCount(new QueryWrapper<TbBusinessPo>().eq("del_state", 0).ge("create_time", startTime).le("create_time", endTime));
    }

    @Override
    public List<BusinessDetailVo> listDetailByIds(List<Long> businessIds) {
        return baseMapper.listDetailByIds(businessIds);
    }

    // 扣减商家补贴金, 汇付支付成功后调用 (目前普通商家给商户转补贴金使用的逻辑)
    @Override
    public Boolean subSubsidyAmt(BusinessSubSubsidyAmtDto businessSubSubsidyAmtDto) {
        Long orderSettleBillId = businessSubSubsidyAmtDto.getId();
        OrderSettleBillVo orderSettleBillVo = orderSettleBillApi.getById(orderSettleBillId).unpack();
        if (orderSettleBillVo == null) {
            log.error("未找到订单结算记录数据，orderSettleBillId：{}", orderSettleBillId);
            return false;
        }

        if (OrderSettleBillTradeStateEnum.SUCCESS.getValue().equals(orderSettleBillVo.getTradeState())) {
            log.error("订单结算记录数据已处理，orderSettleBillId：{}", orderSettleBillId);
            return false;
        }

        Long businessId = businessSubSubsidyAmtDto.getBusinessId();
        Long userId = businessSubSubsidyAmtDto.getUserId();
        String reqSeqId = businessSubSubsidyAmtDto.getReqSeqId();
        BigDecimal feeAmt = businessSubSubsidyAmtDto.getFeeAmt();
        BigDecimal tradeAmt = businessSubSubsidyAmtDto.getTradeAmt();
        BigDecimal subSubsidy = tradeAmt.add(feeAmt);

        TbBusinessPo businessPo = baseMapper.selectById(businessId);
        BigDecimal subsidyAmt = businessPo.getSubsidyAmt();

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 1、扣减商家补贴金
            int count = baseMapper.subSubsidyAmt(businessId, subSubsidy);
            if (count == 0) {
                log.error("扣减商家补贴金失败，orderSettleBillId：{}", orderSettleBillId);
                Throw.isBusinessException("扣减商家补贴金失败");
            }

            // 2、增加商家补贴金流水（补贴扣除和营销补贴服务费）
            TbSubsidyAmtBillPo tbSubsidyAmtBillPo = new TbSubsidyAmtBillPo();
            tbSubsidyAmtBillPo.setBusinessId(businessId);
            tbSubsidyAmtBillPo.setUserId(userId);
            tbSubsidyAmtBillPo.setOrderNo(NoUtils.getSubsidyOrderNo());
            tbSubsidyAmtBillPo.setBillType(BillTypeEnum.EXPEND.getValue());
            tbSubsidyAmtBillPo.setTradeType(SubsidyTradeTypeEnum.DEDUCTION.getValue());
            tbSubsidyAmtBillPo.setRelationTradeNo(reqSeqId);
            tbSubsidyAmtBillPo.setBeforeAmt(subsidyAmt);
            tbSubsidyAmtBillPo.setTradeAmt(tradeAmt);
            tbSubsidyAmtBillPo.setAfterAmt(subsidyAmt.subtract(tradeAmt));
            tbSubsidyAmtBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
            tbSubsidyAmtBillPo.setTradeTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setCreateTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setUpdateTime(LocalDateTime.now());
            count = subsidyAmtBillMapper.insert(tbSubsidyAmtBillPo);
            if (count == 0) {
                log.error("增加商家补贴金扣款流水失败，orderSettleBillId：{}", orderSettleBillId);
                Throw.isBusinessException("增加商家补贴金扣款流水失败");
            }

            tbSubsidyAmtBillPo = new TbSubsidyAmtBillPo();
            tbSubsidyAmtBillPo.setBusinessId(businessId);
            tbSubsidyAmtBillPo.setUserId(userId);
            tbSubsidyAmtBillPo.setOrderNo(NoUtils.getSubsidyOrderNo());
            tbSubsidyAmtBillPo.setBillType(BillTypeEnum.EXPEND.getValue());
            tbSubsidyAmtBillPo.setTradeType(SubsidyTradeTypeEnum.SERVICE.getValue());
            tbSubsidyAmtBillPo.setRelationTradeNo(reqSeqId);
            tbSubsidyAmtBillPo.setBeforeAmt(subsidyAmt.add(tradeAmt));
            tbSubsidyAmtBillPo.setTradeAmt(feeAmt);
            tbSubsidyAmtBillPo.setAfterAmt(subsidyAmt.add(subSubsidy));
            tbSubsidyAmtBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
            tbSubsidyAmtBillPo.setTradeTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setCreateTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setUpdateTime(LocalDateTime.now());
            count = subsidyAmtBillMapper.insert(tbSubsidyAmtBillPo);
            if (count == 0) {
                log.error("增加商家补贴金营销补贴服务费流水失败，orderSettleBillId：{}", orderSettleBillId);
                Throw.isBusinessException("增加商家补贴金营销补贴服务费流水失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<扣减商家补贴金余额+增加商家补贴金流水>事务异常回滚", e);
            return false;
        }

        return true;
    }

    /**
     * 扫描 商家 对 商户 的待转账记录
     */
    @Override
    public void scanSubsidyWaitPayJob() {
        OrderSettleBillDto orderSettleBillDto = new OrderSettleBillDto();
        // 商品补贴
        orderSettleBillDto.setTradeType(OrderSettleBillTradeTypeEnum.SUBSIDY_AMT.getValue());
        // 结算池商家
//        orderSettleBillDto.setBusinessFinancialAccountType(FinancialAccountTypeEnum.PLATFORM.getValue());
        // 普通商户
//        orderSettleBillDto.setMerchantFinancialAccountType(FinancialAccountTypeEnum.SELF.getValue());
        // 待支付
        orderSettleBillDto.setTradeState(OrderSettleBillTradeStateEnum.WAIT.getValue());
        List<OrderSettleBillVo> orderSettleBillVos = orderSettleBillApi.listByDto(orderSettleBillDto).unpack();
        for (OrderSettleBillVo orderSettleBillVo : orderSettleBillVos) {
            businessSubSubsidyAmt(orderSettleBillVo);
        }
    }

    /**
     * 结算池商家给普通商户转商品补贴
     * 1. 扣减商家补贴余额，如果成功，写入商家余额变更日志，状态为 待支付
     * 2. 商家补贴定时任务去跑 待支付 的商家补贴，从商家余额转账到商户余额
     */
    private void businessSubSubsidyAmt(OrderSettleBillVo orderSettleBillVo) {
        Long businessId = orderSettleBillVo.getBusinessId();
        Long userId = orderSettleBillVo.getUserId();
        // 商户实到补贴
        BigDecimal tradeAmt = orderSettleBillVo.getTradeAmt();
        // 支付手续费 0.2%
        BigDecimal feeAmt = tradeAmt.multiply(Constant.BANK_PAY_FEE_AMT_RATE).setScale(2, BigDecimal.ROUND_DOWN);
        // 发票税点 0.6%
        BigDecimal invoiceAmt = tradeAmt.multiply(Constant.BANK_PAY_INVOICE_AMT_RATE).setScale(2, BigDecimal.ROUND_DOWN);
        // 需要扣减商家的补贴金额：商户实到补贴 + 支付手续费 + 发票税点
        BigDecimal subSubsidy = tradeAmt.add(feeAmt).add(invoiceAmt).setScale(2, BigDecimal.ROUND_DOWN);

        TbBusinessPo businessPo = baseMapper.selectById(businessId);
        // 商家当前余额
        BigDecimal subsidyAmt = businessPo.getSubsidyAmt();

        // 判断商家余额够不够
        if (tradeAmt.compareTo(subsidyAmt) > 0) {
            log.error("[business sub subsidy amt]商家补贴金余额不足，补贴转账失败，orderSettleBillId：{}", orderSettleBillVo.getId());
            return;
        }

        // 对结算单记录加锁
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "businessSubSubsidyAmt:" + orderSettleBillVo.getId());

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            // 1. 扣减商家补贴金
            int count = baseMapper.subSubsidyAmt(businessId, subSubsidy);
            if (count == 0) {
                log.error("[business sub subsidy amt]扣减结算池商家补贴金失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                Throw.isBusinessException("扣减结算池商家补贴金失败");
            }

            // 2. 增加商家补贴金流水 (有个定时任务去跑 pay_state = 待支付 的补贴金流水，给商户进行汇付余额转账)
            TbSubsidyAmtBillPo tbSubsidyAmtBillPo = new TbSubsidyAmtBillPo();
            tbSubsidyAmtBillPo.setBusinessId(businessId);
            tbSubsidyAmtBillPo.setUserId(userId);
            tbSubsidyAmtBillPo.setOrderNo(NoUtils.getSubsidyOrderNo());
            tbSubsidyAmtBillPo.setBillType(BillTypeEnum.EXPEND.getValue());
            tbSubsidyAmtBillPo.setRelationTradeNo(String.valueOf(orderSettleBillVo.getId()));
            tbSubsidyAmtBillPo.setTradeType(SubsidyTradeTypeEnum.DEDUCTION.getValue());
            tbSubsidyAmtBillPo.setBeforeAmt(subsidyAmt);
            tbSubsidyAmtBillPo.setTradeAmt(tradeAmt);
            tbSubsidyAmtBillPo.setAfterAmt(subsidyAmt.subtract(tradeAmt));
            tbSubsidyAmtBillPo.setPayState(PayStateEnum.WAIT.getValue());
            tbSubsidyAmtBillPo.setTradeTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setCreateTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setUpdateTime(LocalDateTime.now());
            count = subsidyAmtBillMapper.insert(tbSubsidyAmtBillPo);
            if (count == 0) {
                log.error("[business sub subsidy amt]增加结算池商家补贴金扣款流水失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                Throw.isBusinessException("增加结算池商家补贴金扣款流水失败");
            }

            // 3. 增加商家补贴手续费流水
            tbSubsidyAmtBillPo = new TbSubsidyAmtBillPo();
            tbSubsidyAmtBillPo.setBusinessId(businessId);
            tbSubsidyAmtBillPo.setUserId(userId);
            tbSubsidyAmtBillPo.setOrderNo(NoUtils.getSubsidyOrderNo());
            tbSubsidyAmtBillPo.setBillType(BillTypeEnum.EXPEND.getValue());
            tbSubsidyAmtBillPo.setTradeType(SubsidyTradeTypeEnum.SERVICE.getValue());
            tbSubsidyAmtBillPo.setRelationTradeNo(String.valueOf(orderSettleBillVo.getId()));
            tbSubsidyAmtBillPo.setBeforeAmt(subsidyAmt.add(tradeAmt));
            tbSubsidyAmtBillPo.setTradeAmt(feeAmt);
            tbSubsidyAmtBillPo.setAfterAmt(subsidyAmt.add(subSubsidy));
            tbSubsidyAmtBillPo.setPayState(PayStateEnum.WAIT.getValue());
            tbSubsidyAmtBillPo.setTradeTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setCreateTime(LocalDateTime.now());
            tbSubsidyAmtBillPo.setUpdateTime(LocalDateTime.now());
            count = subsidyAmtBillMapper.insert(tbSubsidyAmtBillPo);
            if (count == 0) {
                log.error("增加商家补贴金营销补贴服务费流水失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                Throw.isBusinessException("增加商家补贴金营销补贴服务费流水失败");
            }

            OrderSettleBillUpdateStateDto updateStateDto = new OrderSettleBillUpdateStateDto();
            updateStateDto.setId(orderSettleBillVo.getId());
            updateStateDto.setOriginTradeState(OrderSettleBillTradeStateEnum.WAIT.getValue());
            updateStateDto.setTradeState(OrderSettleBillTradeStateEnum.WAIT_HF_TRANSFER.getValue());
            int res = orderSettleBillApi.updateTradeState(updateStateDto).unpack();
            if (res == 0) {
                log.error("更新结算单状态失败，orderSettleBillId：{}, orderSettleBillTradeState:{}, res: {}", orderSettleBillVo.getId(), updateStateDto, res);
                Throw.isBusinessException("更新结算单状态失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(transaction);
            log.error("[business sub subsidy amt]<增加结算池商家补贴金扣款流水失败+增加结算池商家补贴金扣款流水失败>事务异常回滚", e);
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    /**
     * 扫描 商家 对 商户 的补贴待转账记录
     */
    @Override
    public void scanSubsidyWaitTransferJob() {
        SubsidyAmtBillDto subsidyAmtBillDto = new SubsidyAmtBillDto();
        // 补贴扣款
        subsidyAmtBillDto.setTradeType(SubsidyTradeTypeEnum.DEDUCTION.getValue());
        // 待支付
        subsidyAmtBillDto.setPayState(PayStateEnum.WAIT.getValue());
        List<SubsidyAmtBillPageVo> subsidyAmtBillPageVos  = tbSubsidyAmtBillMapper.listSubsidyAmtBill(subsidyAmtBillDto);
        for (SubsidyAmtBillPageVo subsidyAmtBillPageVo : subsidyAmtBillPageVos) {
            transferSubsidyBySubsidyAmtBill(subsidyAmtBillPageVo);
        }
    }

    /**
     * 商家分享海报是否展示商家头像开关
     * @param businessId
     * @param posterShowAvatarState
     * @return
     */
    @Override
    public Integer updatePosterShowAvatarState(Long businessId, Integer posterShowAvatarState) {
        return baseMapper.updatePosterShowAvatarState(businessId, posterShowAvatarState);
    }

    @Override
    public Boolean openPointsMall(Long businessId) {
        TbBusinessPo po = baseMapper.selectById(businessId);
        if (po == null || po.getDelState() != 0) {
            Throw.isBusinessException("糟糕，商家信息找不到了");
        }
        if (po.getPointsMallState().equals(BusinessPointsMallStateEnum.OPEN.getValue())) {
            return true;
        }

        // 看看积分商城设置了没
        BusinessPointsMallSettingsVo pointsMallSettingsVo = tbBusinessPointsMallSettingsMapper.getByBusinessId(businessId);
        if (pointsMallSettingsVo == null) {
            Throw.isBusinessException("请先设置积分规则");
        }

        // 看看加了优惠券了没
        Integer couponCount = tbBusinessPointsMallCouponMapper.selectCount(new QueryWrapper<TbBusinessPointsMallProductPo>()
                .eq("del_state", 0)
                .eq("business_id", businessId));
        if (couponCount == null || couponCount == 0) {
            Throw.isBusinessException("请先设置商城奖品");
        }

        LocalDateTime now = LocalDateTime.now();
        po.setPointsMallState(BusinessPointsMallStateEnum.OPEN.getValue());
        if (po.getPointsMallFirstOpenTime() == null) {
            po.setPointsMallFirstOpenTime(LocalDateTime.now());

            // 第一次开启，写入商城积分统计表
            TbBusinessPointsMallStatPo statPo = new TbBusinessPointsMallStatPo();
            statPo.setBusinessId(businessId);
            statPo.setProductNum(0);
            statPo.setUserNum(0);
            statPo.setTotalPayPoints(BigDecimal.ZERO);
            statPo.setTotalExchangedPoints(BigDecimal.ZERO);
            statPo.setCreateTime(now);
            statPo.setUpdateTime(now);
            int res = mallStatMapper.insert(statPo);
            if (res == 0) {
                Throw.isBusinessException("开通失败，请重试");
            }
        }
        po.setUpdateTime(now);

        return updateById(po);
    }

    @Override
    public Boolean closePointsMall(Long businessId) {
        TbBusinessPo po = baseMapper.selectById(businessId);
        if (po == null || po.getDelState() != 0) {
            Throw.isBusinessException("糟糕，商家信息找不到了");
        }
        po.setPointsMallState(BusinessPointsMallStateEnum.CLOSE.getValue());
        return updateById(po);
    }

    @Override
    public BusinessPointsMallHomePageVo getPointsMallHomePage(Long businessId, Long userId) {
        TbBusinessPo po = baseMapper.selectById(businessId);
        if (po == null || po.getDelState() != 0) {
            Throw.isBusinessException("糟糕，商家信息找不到了");
        }
        BusinessPointsMallHomePageVo homePageVo = new BusinessPointsMallHomePageVo();
        if (!po.getPointsMallState().equals(BusinessPointsMallStateEnum.OPEN.getValue())) {
            return homePageVo;
        }

        // 商家基本信息
        BeanUtils.copyProperties(po, homePageVo);
        // 是否订阅
        Integer count = businessSubscribeMapper.selectCount(new QueryWrapper<TbBusinessSubscribePo>()
                .eq("del_state", 0)
                .eq("business_id", businessId)
                .eq("user_id", userId)
        );
        if (count != null && count > 0) {
            homePageVo.setSubscribeState(2);
        }

        // 积分账户余额
        TbUserPointsAccountPo accountPo = tbUserPointsAccountMapper.getAccount(businessId, userId);
        if (accountPo != null) {
            homePageVo.setRemainPoint(accountPo.getRemainPoint());
        }
        // 积分商城设置
        BusinessPointsMallSettingsVo settingsVo = tbBusinessPointsMallSettingsMapper.getByBusinessId(businessId);
        BeanUtils.copyProperties(settingsVo, homePageVo);

        homePageVo.setId(businessId);

        return homePageVo;
    }

    @Override
    public BusinessPointsMallShareVo sharePointsMall(Long businessId) {
        TbBusinessPo po = baseMapper.selectById(businessId);
        if (po == null || po.getDelState() != 0) {
            Throw.isBusinessException("糟糕，商家信息找不到了");
        }
        if (!po.getPointsMallState().equals(BusinessPointsMallStateEnum.OPEN.getValue())) {
            Throw.isBusinessException("该商家未开启积分商城");
        }

        BusinessPointsMallShareVo shareVo = new BusinessPointsMallShareVo();
        shareVo.setLogo(po.getLogo());
        shareVo.setBusinessId(businessId);
        shareVo.setBusinessShortName(po.getBusinessShortName());
        shareVo.setPosterShowAvatarState(po.getPosterShowAvatarState());

        // 需要对id加锁
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "sharePointsMall:" + businessId);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            // todo 加个表记录，分享过，就不需要再生成小程序码

            // 生成小程序分享码
            WxMiniCodeShareTypeEnum wxMiniCodeShareTypeEnum = WxMiniCodeShareTypeEnum.BUSINESS_POINTS_MALL_SHARE;
            String param = wxMiniCodeShareTypeEnum.getName().replace("BUSINESS_ID", String.valueOf(businessId));
            String miniImgUrl = wxConfig.getWxMiniCode(Constant.BUSINESS_POINTS_MALL_SHARE_URL_PAGE, param, wxMiniCodeShareTypeEnum.getValue(), String.valueOf(businessId));

            if (com.cq.hd.common.utils.StringUtils.isBlank(miniImgUrl)) {
                log.error("生成分享小程序码失败,businessId:{}", businessId);
                Throw.isBusinessException("小程序码生成失败");
            }

            shareVo.setMiniImgUrl(miniImgUrl);

            return shareVo;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    /**
     * 调汇付接口，进行商户补贴金转账
     */
    private void transferSubsidyBySubsidyAmtBill(SubsidyAmtBillPageVo subsidyAmtBillPageVo) {
        // order_settle_bill 表的 id
        Long orderSettleBillId = Long.valueOf(subsidyAmtBillPageVo.getRelationTradeNo());
        OrderSettleBillVo orderSettleBillVo = orderSettleBillApi.getById(orderSettleBillId).unpack();
        if (orderSettleBillVo == null) {
            log.error("未找到订单结算记录数据，orderSettleBillId：{}", orderSettleBillId);
            return;
        }

        log.error("汇付转账接口：{}", orderSettleBillVo);

        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "transferSubsidyBySubsidyAmtBill:" + orderSettleBillId);
        try {
            Boolean result = orderSettleBillApi.transferByOrderSettleBill(orderSettleBillVo).unpack();
            log.info("汇付支付结果：{}", result);
            if (result) {
                tbSubsidyAmtBillMapper.updateByRelationTradeNo(subsidyAmtBillPageVo.getRelationTradeNo(), PayStateEnum.SUCCESS.getValue());
            }
        } catch (Exception e) {
            log.error("[transferSubsidyBySubsidyAmtBill]汇付余额转账失败", e);
        } finally {
            LockUtils.unlock(lockKey);
        }
    }
}
